mod error_context_dyn_trait;
mod error_context_trait;

pub use error_context_dyn_trait::ErrorContextDynTrait;
pub use error_context_trait::ErrorContextTrait;
use std::error::Error;

#[derive(Debug)]
pub struct SysError {
    message: String,
    source: Box<dyn std::error::Error + 'static>,
}

impl<T> ErrorContextTrait<T> for Result<T, Box<dyn std::error::Error>> {
    fn with_error_context(self, context: &str) -> Result<T, Box<dyn std::error::Error>> {
        self.map_err(|e| {
            // 创建一个新的错误类型，包含原始错误和上下文信息
            Box::new(SysError {
                message: context.to_string(),
                source: e,
            }) as Box<dyn std::error::Error>
        })
    }
}
impl<T> ErrorContextDynTrait<T> for Result<T, Box<dyn Error>> {
    fn with_error_context(self, context: &str) -> Result<T, Box<dyn Error>> {
        Ok(self.map_err(|e| {
            Box::new(SysError {
                message: context.to_string(),
                source: e,
            })
        })?)
    }
}

// 为MyError实现error::Error和fmt::Display traits
impl std::error::Error for SysError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        Some(&*self.source)
    }
}

impl std::fmt::Display for SysError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}:{}", self.message, self.source)
    }
}

impl SysError {
    pub fn msg(msg: &str) -> Self {
        SysError {
            message: msg.to_string(),
            source: Box::new(std::io::Error::new(
                std::io::ErrorKind::Other,
                "Custom Error, No source error",
            )),
        }
    }
}

// 创建一个函数来封装错误处理逻辑
pub fn with_context<E>(err: E, context: &str) -> SysError
where
    E: std::error::Error + 'static,
{
    SysError {
        message: context.to_string(),
        source: Box::new(err),
    }
}
